#include <stdio.h>
#include <stdlib.h>
#include <ogcsys.h>
#include <wiiuse/wpad.h>

struct timespec _wiilight_timeOn;

struct timespec _wiilight_timeOff;

int WIILIGHT_IsOn;
int WIILIGHT_Level;

void _wiilight_turn ( int enable );
static void * _wiilight_loop ( void *arg );
static vu32 *_wiilight_reg = ( u32* ) 0xCD0000C0;
lwp_t _wiilight_thread;


void WIILIGHT_Init();
void WIILIGHT_TurnOn();
int WIILIGHT_GetLevel();
int WIILIGHT_SetLevel ( int level );

void WIILIGHT_Toggle();
void WIILIGHT_TurnOff();

void WIILIGHT_Init() {
	_wiilight_timeOn.tv_sec = ( time_t ) 0;
	_wiilight_timeOff.tv_sec = ( time_t ) 0;
	WIILIGHT_IsOn = 0;
	WIILIGHT_SetLevel ( 0 );
}


int WIILIGHT_GetLevel() {
	return WIILIGHT_Level;
}

//
// here is where we set the light intensity
// it turns on the light and
// waits level*40000 nanoseconds
// (so, if it is 255 it will wait for 10200000 nanoseconds)
// (that means ~ 1/100secs)
//
// for the time turned off it is 10200000-level_on
// (so, if level is 255, it will wait for 0 seconds)
// (that means full light intensity)
//

int WIILIGHT_SetLevel ( int level ) {//0 to 255
	long level_on;
	long level_off;

	if ( level > 255 ) level = 255;

	if ( level < 0 ) level = 0;

	level_on = level * 40000;

	level_off = 10200000 - level_on;

	_wiilight_timeOn.tv_nsec = level_on;

	_wiilight_timeOff.tv_nsec = level_off;

	WIILIGHT_Level = level;

	return level;
}

//
// just turn one bit
//

void _wiilight_turn ( int enable ) {
	u32 val = ( *_wiilight_reg & ~0x20 );

	if ( enable ) val |= 0x20;

	*_wiilight_reg = val;
}

void WIILIGHT_TurnOff() {

	WIILIGHT_IsOn = false;

}

//
// Set the var on, and start the looping thread
//

void WIILIGHT_TurnOn() {

	WIILIGHT_IsOn = true;
	LWP_CreateThread ( &_wiilight_thread, _wiilight_loop, NULL, NULL, 0, 80 );

}

void WIILIGHT_Toggle() {

	if ( WIILIGHT_IsOn ) {
		WIILIGHT_TurnOff();
	}
	else {
		WIILIGHT_TurnOn();
	}

}

//
// This is the looping thread.. it just loops
// turning on and off the light depending on the timing
// specified by SetLevel()
//

static void * _wiilight_loop ( void *arg ) {

	struct timespec timeOn;

	struct timespec timeOff;

	while ( WIILIGHT_IsOn ) {
		timeOn = _wiilight_timeOn;
		timeOff = _wiilight_timeOff;
		_wiilight_turn ( 1 );
		nanosleep ( &timeOn );

		if ( timeOff.tv_nsec > 0 ) _wiilight_turn ( 0 );

		nanosleep ( &timeOff );
	}

	return NULL;

}

